﻿using System;
using System.Windows;
using System.Windows.Input;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Speech.Synthesis;

using Coogle.Core;
using Coogle.DataAccess;
using System.Configuration;

namespace Coogle
{
    public partial class MainWindow : Window
    {
        private static readonly String s_connectionString = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
        private readonly DbGateway db;
        private SpeechSynthesizer speechSynthesizer;

        public MainWindow()
        {
            InitializeComponent();
            db = new DbGateway(s_connectionString);
            speechSynthesizer = new SpeechSynthesizer();
            Closing += (s, e) => speechSynthesizer.Dispose();
        }

        private void txtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key.Equals(Key.Enter) == false)
                return;

            DoSearch();
        }

        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            DoSearch();
        }

        private Visibility VisibilityFor<TArg>(TArg arg, Predicate<TArg> visibilityPredicate)
        {
            if (visibilityPredicate(arg))
                return Visibility.Visible;
            return Visibility.Collapsed;
        }

        private Boolean Speech<TArg>(TArg arg, String message, Predicate<TArg> speechPredicate)
        {
            if (speechPredicate(arg))
            {
                speechSynthesizer.SpeakAsync(message);
                return true;
            }
            return false;
        }

        private void DoSearch()
        {
            var cc = ContainerCode.Parse(txtSearch.Text);
            var container = db.FindSingle(new SelectContainer(cc));
            var shippings = new ObservableCollection<Shipping>(db.Find(new SelectShippings(cc)));

            BindContainer(container);
            BindShippings(shippings);

            Pipe(() => Speech(container, "container not found", c => c == null),
                () => Speech(shippings, "shippings not found", s => s.Count == 0));
        }

        private void BindShippings(ObservableCollection<Shipping> shippings)
        {
            lstShippings.ItemsSource = shippings;
            shippingsList.Visibility = VisibilityFor(shippings, s => s.Count > 0);
        }

        private void BindContainer(Container container)
        {
            containerDetails.DataContext = container;
            containerDetails.Visibility = VisibilityFor(container, c => c != null);
        }

        private void Pipe(params Func<Boolean>[] handlers)
        {
            foreach (var handler in handlers)
                if (handler())
                    return;
        }
    }
}
